
<template>

  <div>
    <el-row>
      <el-col :span="20">
        <el-input  v-if="column.display"
                   v-model="val"
                   :disabled="column.disabled"
                  >
        </el-input>
      </el-col>

      <el-col :span="4">
        <el-button slot="append" icon="el-icon-search" @click="barcodeClick" circle></el-button>
      </el-col>
    </el-row>
  </div>


  <el-dialog  v-model="dialogVisible" title="条形码扫描器"  >
    <el-container>
<!--      <el-header>-->
<!--        <h1 style="text-align: center; color: #409EFF;">条形码扫描器</h1>-->
<!--      </el-header>-->
      <el-main>
        <div class="scanner-container">
          <el-alert
              title="HTTP环境限制提示"
              description="由于HTTP协议的安全限制，部分浏览器可能无法正常调用摄像头。建议在生产环境中使用HTTPS协议部署。"
              type="warning"
              show-icon
              v-show="!videoDevices||videoDevices.length==0"
              style="margin-bottom: 20px;">
          </el-alert>

          <div class="video-wrapper">
            <video ref="videoElement" id="video" class="scanner-video" autoplay></video>
            <div class="scan-overlay">
              <div class="scan-frame"></div>
              <div class="scan-line"></div>
            </div>
          </div>

          <div class="control-panel">
            <el-button type="primary" @click="startScan" :loading="isScanning" :disabled="isScanning">
              {{ isScanning ? '扫描中...' : '开始扫描' }}
            </el-button>
            <el-button @click="stopScan" :disabled="!isScanning">
              停止扫描
            </el-button>
            <el-button @click="switchCamera" :disabled="!isScanning || videoDevices.length < 2">
              切换摄像头
            </el-button>
          </div>

          <div class="status-message" v-if="statusMessage">
            <i class="el-icon-info"></i> {{ statusMessage }}
          </div>

          <el-card class="result-panel" v-if="scanResult">
            <template #header>
              <div style="display: flex; justify-content: space-between; align-items: center;">
                <span>扫描结果</span>
                <el-button type="text" @click="copyResult">复制</el-button>
              </div>
            </template>
            <div style="font-size: 16px; font-weight: bold; word-break: break-all;">
              {{ scanResult }}
            </div>
          </el-card>

          <el-collapse v-model="activeNames" style="margin-top: 20px;">
            <el-collapse-item title="扫描记录" name="history">
              <el-table :data="scanHistory" style="width: 100%">
                <el-table-column prop="time" label="时间" width="180"></el-table-column>
                <el-table-column prop="result" label="结果"></el-table-column>
                <el-table-column label="操作" width="120">
                  <template #default="scope">
                    <el-button size="mini" @click="copyHistoryItem(scope.row)">复制</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </el-collapse-item>
          </el-collapse>
        </div>
      </el-main>
    </el-container>
  </el-dialog>


</template>

<script>


import * as ZXing from "@zxing/library";

export default {
  name: 'JrBarcode',
  inject: ['getViewFormData'],
  props: ['column', 'modelValue'],

  data() {
    const val = this.viewFormData?.form ? this.viewFormData.form[this.column.prop] : '';
    const { disabled, display } = this.column || {};
    return {
      val,
      disabled,
      display,
      dialogVisible:false,
      codeReader: null,
      videoDevices: [],
      selectedDeviceId: null,
      scanResult: null,
      statusMessage: '',
      isScanning: false,
      scanHistory: [],
      activeNames: ['history']
    };
  },
  async mounted() {

  },
  beforeDestroy() {
    this.stopScan();
  },
  methods: {
    barcodeClick(){
      this.dialogVisible =true;
      setTimeout(() => {
       this.initializeScanner()
      }, 500)

    },
    async initializeScanner() {
      try {
        this.codeReader = new ZXing.BrowserMultiFormatReader();
        this.statusMessage = '正在初始化扫描器...';

        // 获取可用摄像头设备
        this.videoDevices = await this.codeReader.listVideoInputDevices();

        if (this.videoDevices.length === 0) {
          this.statusMessage = '未找到可用的摄像头设备';
          return;
        }

        // 尝试选择后置摄像头
        const backCamera = this.videoDevices.find(device =>
            device.label.toLowerCase().includes('back')
        );

        this.selectedDeviceId = backCamera ? backCamera.deviceId : this.videoDevices[0].deviceId;

        this.statusMessage = '扫描器初始化完成，点击开始扫描';

      } catch (error) {
        console.error('初始化扫描器失败:', error);
        this.handleError(error);
      }
    },

    async startScan() {
      if (!this.codeReader) {
        this.$message.error('扫描器未正确初始化');
        return;
      }

      try {
        this.isScanning = true;
        this.statusMessage = '正在启动摄像头...';

        this.codeReader.decodeFromVideoDevice(
            this.selectedDeviceId,
            'video',
            (result, error) => {
              if (result) {
                this.scanResult = result.text;
                this.statusMessage = '扫描成功!';

                // 添加到历史记录
                this.scanHistory.unshift({
                  time: new Date().toLocaleString(),
                  result: result.text
                });

                this.$message.success('扫描成功: ' + result.text);
              }

              if (error && !(error instanceof Error)) {
                console.log('扫描中:', error);
              }
            });

      } catch (error) {
        this.handleError(error);
      }
    },

    stopScan() {
      if (this.codeReader) {
        this.codeReader.reset();
        this.isScanning = false;
        this.statusMessage = '扫描已停止';
        this.dialogVisible =false
        this.viewFormData.form[this.column.prop] = this.scanResult
        this.val = this.scanResult
      }
    },

    switchCamera() {
      if (this.videoDevices.length < 2) {
        this.$message.warning('只有一个摄像头可用');
        return;
      }

      const currentIndex = this.videoDevices.findIndex(
          device => device.deviceId === this.selectedDeviceId
      );

      const nextIndex = (currentIndex + 1) % this.videoDevices.length;
      this.selectedDeviceId = this.videoDevices[nextIndex].deviceId;

      this.stopScan();
      setTimeout(() => {
        this.startScan();
      }, 500);
    },

    copyResult() {
      if (!this.scanResult) {
        this.dialogVisible =false
        return;
      }

      const textArea = document.createElement('textarea');
      textArea.value = this.scanResult;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand('copy');
      document.body.removeChild(textArea);
      this.$message.success('结果已复制到剪贴板');
      this.dialogVisible =false
      this.viewFormData.form[this.column.prop] = this.scanResult
      this.val = this.scanResult
    },

    copyHistoryItem(item) {
      const textArea = document.createElement('textarea');
      textArea.value = item.result;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand('copy');
      document.body.removeChild(textArea);
      this.$message.success('结果已复制到剪贴板');
    },

    handleError(error) {
      console.error('扫描错误:', error);

      switch (error?.name) {
        case 'NotAllowedError':
          this.statusMessage = '请允许摄像头访问权限';
          this.$message.error('摄像头访问被拒绝，请检查浏览器权限设置');
          break;
        case 'NotFoundError':
          this.statusMessage = '未找到摄像头设备';
          this.$message.error('未检测到摄像头设备');
          break;
        case 'NotSupportedError':
          this.statusMessage = '请在HTTPS环境或localhost下使用';
          this.$message.error('当前环境不支持摄像头访问');
          break;
        case 'NotReadableError':
          this.statusMessage = '摄像头被占用，请关闭其他使用摄像头的应用';
          break;
        default:
          this.statusMessage = '扫描失败:' + error?.message || '未知错误';
          this.isScanning = false;
      }
    }
  }
}

</script>

<style>
.full-screen-dialog .el-dialog {
  width: 100% !important;
  top: 0px !important;
  margin-top: 0px !important;
  height: calc(100% - 55px); /* 减去头部的高度 */
  margin-bottom: 0;
}

.full-screen-dialog .el-dialog__header {
  padding: 20px;
  background-color: #f5f7fa;
}

.full-screen-dialog .el-dialog__body {
  padding: 20px 40px;
}


</style>
<style scoped>
.scanner-container {

  margin: 0 auto;
  padding: 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 20px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  color: white;
}

.scanner-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.close-btn {
  background: rgba(255, 255, 255, 0.2);
  border: none;
  padding: 10px 20px;
  border-radius: 10px;
  color: white;
  cursor: pointer;
  transition: all 0.3s ease;
}

.close-btn:hover {
  background: rgba(255, 255, 255, 0.3);
  transform: translateY(-2px);
}

.video-wrapper {
  position: relative;
  width: 100%;
  height: 400px;
  border-radius: 15px;
  overflow: hidden;
  background: #000;
}

.scanner-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.scan-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.scan-frame {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 250px;
  height: 100px;
  border: 2px solid #00ff33;
  border-radius: 10px;
  box-shadow: 0 0 20px #00ff33;
}

.scan-line {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 250px;
  height: 2px;
  background: linear-gradient(90deg, transparent, #00ff33, transparent);
  animation: scan 2s ease-in-out infinite;
}

@keyframes scan {
  0%, 100% { top: 30%; }
  50% { top: 70%; }
}

.scanner-controls {
  display: flex;
  gap: 15px;
  justify-content: center;
  margin: 20px 0;
}

.control-btn {
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.3);
  padding: 12px 20px;
  border-radius: 25px;
  color: white;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  gap: 8px;
}

.control-btn:hover {
  background: rgba(255, 255, 255, 0.25);
  transform: translateY(-2px);
}

.scan-result {
  background: rgba(255, 255, 255, 0.1);
  padding: 20px;
  border-radius: 15px;
  margin-top: 20px;
  text-align: center;
}

.result-text {
  font-size: 18px;
  font-weight: bold;
  margin: 10px 0;
  word-break: break-all;
}

.copy-btn {
  background: #4CAF50;
  border: none;
  padding: 10px 20px;
  border-radius: 20px;
  color: white;
  cursor: pointer;
  transition: all 0.3s ease;
}

.copy-btn:hover {
  background: #45a049;
  transform: translateY(-2px);
}

.status-message {
  text-align: center;
  margin-top: 15px;
  font-style: italic;
  opacity: 0.8;
}
</style>
